<?php

namespace App\Service\act;

use App\Enum\EnumType;
use App\Service\BaseService;
use App\Service\SysConfService;
use App\Service\UserService;
use Hyperf\DbConnection\Db;
use function Hyperf\Support\env;

/**
 * 任务服务
 */
class TaskService extends BaseService
{
    // 表名
    protected static string $tbName = 'act_task';

    // 奖品发放记录
    protected array $prizeLogs = [];
    // cash记录
    public array $userCoinLogs = [];
    // bonus记录
    public array $userBonusLogs = [];
    // 用户发放奖品数据
    public array $userPrizeData = [
//        // 现金余额
//        EnumType::PRIZE_TYPE_CASH_CHAR => 0,
//        // 奖励余额
//        EnumType::PRIZE_TYPE_BONUS_CHAR => 0,
//        // 抽奖次数
//        EnumType::PRIZE_TYPE_DRAW_NUM_CHAR => [],
    ];
    // 当前用户
    public array $currUser = [];

    /**
     * 获取任务列表
     * @param array $params
     * @param bool $all
     * @param bool $cached
     * @return array|mixed|mixed[]
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function getTaskList(array $params = [], bool $all = false, bool $cached = true): mixed
    {
        // 从缓存获取
        $params['all'] = $all;
        $hTbName = EnumType::TASK_LIST_CACHE_PREFIX.self::createHashKey($params);
        $cacheList = self::getCache($hTbName);
        if ($cacheList && $cached) {
            $list = $cacheList['data'] ? json_decode($cacheList['data'], true) : [];
        } else {
            // 字段
            $field = empty($params['field']) ? [self::$tbName.'.*', 'active.name as act_name'] : $params['field'];
            // 排序
            $order = empty($params['order']) ? 'br_'.self::$tbName.'.sort desc' : $params['order'];

            $model = self::getPoolTb(self::$tbName)
                ->leftJoin('active', 'act_id', '=', 'active.id')
                ->where(self::$tbName.'.is_show', EnumType::IS_SHOW_YES)
                ->where(self::$tbName.'.is_del', EnumType::IS_DEL_NO)
                ->when(!empty($params['act_id']), function ($query) use ($params) {
                    $query->where('act_id', $params['act_id']);
                })
                ->when(!empty($params['condition_type']), function ($query) use ($params) {
                    $query->where('condition_type', $params['condition_type']);
                })
                ->when(!empty($params['c_types']), function ($query) use ($params) {
                    $query->whereIn('condition_type', $params['c_types']);
                })
                ->when(!empty($params['task_key']), function ($query) use ($params) {
                    $query->where('task_key', $params['task_key']);
                })
                ->orderByRaw($order);
            $list = $all ? $model->select($field)->get()->toArray() : $model->paginate(empty($params['page_size']) ? self::$pageSize : (int)$params['page_size'], $field)->toArray();
            // 数据缓存
            self::setCache($hTbName, ['data' => json_encode($list)], self::$cacheExpire);
        }

        // 获取奖品列表
        $prizeList = self::getPidOfPrize();

        if ($all) {
            foreach ($list as &$value) {
                self::handleInfo($value, $prizeList);
            }
        } else {
            foreach ($list['data'] as &$value) {
                self::handleInfo($value, $prizeList);
            }
        }

        return $list;
    }

    protected static function handleInfo(array &$info, array $prizeList): void
    {
        // 任务条件
        if(!empty($info['task_conditions'])) $info['task_conditions'] = json_decode($info['task_conditions'], true);
        // 任务奖品
        if(!empty($info['prizes'])) {
            $info['prizes'] = json_decode($info['prizes'], true);
            $info['prize_list'] = [];
            foreach ($info['prizes'] as $pid) {
                if (!isset($prizeList[$pid])) continue;
                $info['prize_list'][] = [
                    'prize_id' => $pid,
                    'act_id' => $prizeList[$pid]['act_id'],
                    'prize_name' => $prizeList[$pid]['prize_name'],
                    'prize_type' => $prizeList[$pid]['prize_type'],
                    'prize_unit' => $prizeList[$pid]['prize_unit'],
                    'prize_value' => $prizeList[$pid]['prize_value'],
                ];
            }
        } else {
            $info['prizes'] = $info['prize_list'] = [];
        }

        // 任务图标
        if (!empty($info['task_icon'])) {
            $info['task_icon'] = env('URL_DOMAIN_ADMIN') . $info['task_icon'];
        }

        // 奖项图标
        if (!empty($info['pobj_icon'])) {
            $info['pobj_icon'] = env('URL_DOMAIN_ADMIN') . $info['pobj_icon'];
        }

    }

    /**
     * 获取奖品列表
     * @return array|mixed|mixed[]
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function getPrizeList(): mixed
    {
        $hTbName = EnumType::PRIZE_LIST_CACHE_PREFIX;
        $cacheList = self::getCache($hTbName);
        if ($cacheList) {
            $list = $cacheList['data'] ? json_decode($cacheList['data'], true) : [];
        } else {
            $list = self::getPoolTb('act_prize')
                ->where('is_show', EnumType::IS_SHOW_YES)
                ->where('is_del', EnumType::IS_DEL_NO)
                ->select()
                ->get()->toArray();
            // 数据缓存
            self::setCache($hTbName, ['data' => json_encode($list)], self::$cacheExpire);
        }

        return $list;
    }

    /**
     * 获取以奖品ID为下标的奖品列表
     * @return array
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function getPidOfPrize(): array
    {
        $prizeList_ = self::getPrizeList();
        $prizeList = [];
        foreach ($prizeList_ as $pl) {
            $prizeList[$pl['prize_id']] = $pl;
        }
        return $prizeList;
    }

    /**
     * 获取奖项列表
     * @param int $actId
     * @param string $pobjKey
     * @param bool $cached
     * @return mixed
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function getPrizeObjList($actId, string $pobjKey = '', bool $cached = true): mixed
    {
        if (is_array($actId)) {
            $hashKey = self::createHashKey($actId);
        } else {
            $hashKey = $actId;
        };
        $hTbName = EnumType::PRIZE_OBJ_LIST_CACHE_PREFIX.$hashKey;
        $cacheList = self::getCache($hTbName);
        if ($cacheList && $cached) {
            $list = $cacheList['data'] ? json_decode($cacheList['data'], true) : [];
        } else {
            $list = self::getPoolTb('act_prize_obj')
                ->where('is_show', EnumType::IS_SHOW_YES)
                ->where('is_del', EnumType::IS_DEL_NO)
                ->when(is_array($actId), function ($query) use ($actId) {
                    $query->whereIn('act_id', $actId);
                })
                ->when(!is_array($actId), function ($query) use ($actId) {
                    $query->where('act_id', $actId);
                })
                ->when(!empty($pobjKey), function ($query) use ($pobjKey) {
                    $query->where('pobj_key', $pobjKey);
                })
                ->select()
                ->orderBy('sort', 'desc')
                ->get()->toArray();

            // 获取奖品列表
            $prizeList = self::getPidOfPrize();
            foreach ($list as &$val) {
                self::handleInfo($val, $prizeList);
            }
            // 数据缓存
            self::setCache($hTbName, ['data' => json_encode($list)], self::$cacheExpire);
        }

        return $list;
    }

    /**
     * 处理用户任务进度
     * @param int $uid 用户ID
     * @param int $conditionType 条件类型
     * @param int $conditionValue 条件值
     * @param int $progress 任务进度值
     * @param array $params
     * @param bool $isGroup 当前系统任务是否是一组任务，如果是一组则存在完成先后顺序
     * @return bool|void
     */
    public function changeUserTaskProgress(int $uid, int $conditionType = EnumType::TASK_CONDITION_TYPE_TERRACES_BET, int $conditionValue = 0, int $progress = 1, array $params = [], bool $isGroup = true)
    {
        try {
            $currTime = time(); // 当前时间
            $todayTime = strtotime(date(self::$dateFormat, $currTime)); // 今日开始时间
            // 获取系统生效的任务列表
            $paramsTask = [];
            !empty($params['act_id']) && $paramsTask['act_id'] = $params['act_id'];
            !empty($params['condition_type']) && !$isGroup && $paramsTask['condition_type'] = $params['condition_type'];
            !empty($params['task_key']) && $paramsTask['task_key'] = $params['task_key'];
            $taskList = self::getTaskList($paramsTask, true);
            if (empty($taskList)) return true;

            // 获取用户有效的任务
            $userTaskList = self::getUidPartTb('act_user_task', $uid)
                ->where('uid', $uid)
                ->where('is_valid', EnumType::USER_TASK_IS_VALID_YES)
                ->whereIn('task_id', array_column($taskList, 'task_id'))
                ->orderBy('curr_times')
                ->select()->get()->toArray();
            $userTasks = $userTaskCompletedNum = [];
            foreach ($userTaskList as $ut) {
                // 组装用户不同轮次任务
                $userTasks[$ut['task_id'].'_'.$ut['curr_times']] = $ut;

                // 统计用户任务已完成数量
                if ($ut['status'] == EnumType::USER_TASK_STATUS_COMPLETED) {
                    if (isset($userTaskCompletedNum[$ut['task_id']])) {
                        $userTaskCompletedNum[$ut['task_id']] += 1;
                    } else {
                        $userTaskCompletedNum[$ut['task_id']] = 1;
                    }
                }
            }
            unset($userTaskList);

            // 获取当前用户信息
            $this->currUser = UserService::getUserInfo($uid);
            if (!$this->currUser) {
                return false;
            }

            // 处理任务进度
            $utUpdateData = $utAddData = [];
            $openNextTask = false; // 是否开启下一个任务（同一组任务中）
            $checkField = self::getTaskConditionField($conditionType); // 任务条件检测字段
            $lastTaskCurrTimes = $userTaskCompletedNum[$taskList[count($taskList) - 1]['task_id']] ?? 0; // 用户最后一个任务已完成的轮次
            foreach ($taskList as $tk => $task) {
                // 用户当前任务进行轮次
                $taskCurrTimes = ($userTaskCompletedNum[$task['task_id']] ?? 0) + 1;
                $task['curr_times'] = $taskCurrTimes; // 用户当前任务轮次
                // 用户任务key索引
                $userTaskIndexKey = $task['task_id'] . '_' . $taskCurrTimes;
                // 同一组任务，需检测前面任务是否完成
                if ($isGroup) {
                    // 是否有任务进度
                    if (isset($userTasks[$userTaskIndexKey])) { // 有任务进度
                        $ut = $userTasks[$userTaskIndexKey];
                        if ($ut['status'] == EnumType::USER_TASK_STATUS_IN_HAND) { // 任务进行中
                            // 检测任务限定条件
                            if (!self::checkTaskLimitConditions($params, $task['task_conditions'])) {
                                break;
                            }

                            // 检测是否是当前任务条件类型
                            if ($ut['condition_type'] == $conditionType && $task['task_conditions'][$checkField['check_value']] <= $conditionValue) {
                                // 更新任务进度
                                $utUpdateData[] = $this->getUpdateUserTaskData($ut, $task, $progress, $checkField, $currTime);
                            }
                            break; // 退出循环
                        } elseif ($ut['status'] == EnumType::USER_TASK_STATUS_COMPLETED) { // 任务已完成
                            // 检测任务完成时间，是否开启下一任务
                            if (strtotime($ut['complete_time']) < $todayTime) {
                                $openNextTask = true;
                            }
                        }
                    } else { // 没有任务进度
                        // 检测同一组任务中最后一个任务已完成轮次，当前任务轮次只能比最后任务大1个轮次
                        if ($taskCurrTimes - $lastTaskCurrTimes !== 1) {
                            // 检测当前任务上一轮完成时间，是否开启或关闭下一任务
                            $userTaskIndexKey = $task['task_id'] . '_' . ($taskCurrTimes - 1);
                            if (isset($userTasks[$userTaskIndexKey])) {
                                $ut = $userTasks[$userTaskIndexKey];
                                if (strtotime($ut['complete_time']) < $todayTime) {
                                    $openNextTask = true;
                                } else {
                                    $openNextTask = false;
                                }
                            }
                            continue;
                        }

                        // 检测任务限定条件
                        if (!self::checkTaskLimitConditions($params, $task['task_conditions'])) {
                            break;
                        }

                        // 如果已开启下一个任务且满足当前任务条件类型，则添加任务进度数据
                        if (($tk == 0 || $openNextTask) && $task['condition_type'] == $conditionType && $task['task_conditions'][$checkField['check_value']] <= $conditionValue) {
                            // 检测任务最大完成次数是否达标
                            if ($task['max_complete_num'] > 0 && $task['max_complete_num'] < $taskCurrTimes) {
                                break;
                            }
                            // 添加任务进度
                            $utAddData[] = $this->getAddUserTaskData($uid, $task, $progress, $checkField, $currTime);
                        }
                        break;
                    }
                } else { // 非同一组任务，如果满足任务条件可一并累计任务进度
                    // 检测任务限定条件
                    if (!self::checkTaskLimitConditions($params, $task['task_conditions'])) {
                        continue; // 跳过当前任务，进入下一个任务
                    }

                    // 是否有任务进度
                    if (isset($userTasks[$userTaskIndexKey])) { // 有任务进度
                        $ut = $userTasks[$userTaskIndexKey];
                        if ($ut['status'] == EnumType::USER_TASK_STATUS_IN_HAND) { // 任务进行中
                            // 检测是否是当前任务条件类型
                            if ($ut['condition_type'] == $conditionType && $task['task_conditions'][$checkField['check_value']] <= $conditionValue) {
                                // 更新任务进度
                                $utUpdateData[] = $this->getUpdateUserTaskData($ut, $task, $progress, $checkField, $currTime);
                            }
                        } elseif ($ut['status'] == EnumType::USER_TASK_STATUS_COMPLETED) { // 任务已完成
                            // 检测任务最大完成次数是否达标
                            if ($task['max_complete_num'] > 0 && $task['max_complete_num'] < $taskCurrTimes) {
                                continue; // 跳过当前任务，进入下一个任务
                            }
                            // 重新添加任务进度
                            $utAddData[] = $this->getAddUserTaskData($uid, $task, $progress, $checkField, $currTime);
                        }
                    } else { // 没有任务进度
                        // 添加任务进度
                        $utAddData[] = $this->getAddUserTaskData($uid, $task, $progress, $checkField, $currTime);
                    }
                }
            }
            unset($taskList);

            // 无任务进度更新
            if (empty($utUpdateData) && empty($utAddData)) {
                return true;
            }

            // 保存数据
            Db::transaction(function () use ($uid, $utUpdateData, $utAddData) {
                // 新增用户任务进度数据
                if (!empty($utAddData)) {
                    self::getUidPartTb('act_user_task', $uid)->insert($utAddData);
                }
                // 更新用户任务进度数据
                if (!empty($utUpdateData)) {
                    $tbName = 'br_act_user_task_' . substr((string)$uid, -1, 1);
                    $sql = self::getBatchUpdateSql($tbName, $utUpdateData,'utask_id');
                    if (!empty($sql)) Db::update($sql);
                }

                // 保存奖品发放数据
                self::saveSendPrizeData();
            });

            return true;
        } catch (\Throwable $e) {
            self::logger()->alert('TaskService.changeUserTaskProgress.Exception：' . $e->getMessage() . $e->getTraceAsString());
            return false;
        }
    }

    /**
     * 检测任务限定条件
     * @param array $params
     * @param array $taskConditions
     * @return bool
     */
    protected static function checkTaskLimitConditions(array $params, array $taskConditions): bool
    {
        // 检测游戏ID是否包含在条件
        if (!empty($params['game_id']) && !empty($taskConditions['games']) && !in_array($params['game_id'], $taskConditions['games'])) {
            return false;
        }
        // 检测游戏厂商是否包含在条件
        if (!empty($params['terrace_id']) && !empty($taskConditions['terraces']) && !in_array($params['terrace_id'], $taskConditions['terraces'])) {
            return false;
        }
        return true;
    }

    /**
     * 获取添加用户任务数据
     * @param int $uid
     * @param array $task
     * @param int $progress
     * @param array $checkField
     * @param int $currTime
     * @return array
     */
    protected function getAddUserTaskData(int $uid, array $task, int $progress, array $checkField, int $currTime): array
    {
        // 添加任务进度
        $addData = [
            'act_id' => $task['act_id'],
            'uid' => $uid,
            'task_id' => $task['task_id'],
            'task_name' => $task['task_name'],
            'condition_type' => $task['condition_type'],
            'status' => EnumType::USER_TASK_STATUS_IN_HAND,
            'curr_times' => $task['curr_times'],
            'create_time' => date(self::$dateTimeFormat, $currTime),
            'update_time' => date(self::$dateTimeFormat, $currTime),
        ];
        // 计算任务数据
        $this->computeTaskData($addData, $task, $progress, $checkField, $currTime);
        return $addData;
    }

    /**
     * 获取添加用户任务数据
     * @param array $userTasks
     * @param array $task
     * @param int $progress
     * @param array $checkField
     * @param int $currTime
     * @return array
     */
    protected function getUpdateUserTaskData(array $userTasks, array $task, int $progress, array $checkField, int $currTime): array
    {
        // 更新任务进度
        $updateData = [
            'uid' => $userTasks['uid'],
            'utask_id' => $userTasks['utask_id'],
            'task_id' => $task['task_id'],
            'task_name' => $task['task_name'],
            'condition_type' => $task['condition_type'],
            'status' => EnumType::USER_TASK_STATUS_IN_HAND,
            'update_time' => date(self::$dateTimeFormat, $currTime),
        ];
        // 计算任务数据
        $this->computeTaskData($updateData, $task, $userTasks['complete_progress'] + $progress, $checkField, $currTime);
        return $updateData;
    }

    /**
     * 计算任务数据
     * @param array $data
     * @param array $task
     * @param int $progress
     * @param array $checkField
     * @param int $currTime
     * @return void
     */
    protected function computeTaskData(array &$data, array $task, int $progress, array $checkField, int $currTime): void
    {
        // 任务条件
        $data['total_progress'] = $task['task_conditions'][$checkField['progress_value']]; // 任务总进度
        $data['complete_progress'] = $progress; // 已完成进度
        // 检测任务进度是否完成
        if ($data['complete_progress'] >= $data['total_progress']) {
            $data['complete_progress'] = $data['total_progress'];
            $data['status'] = EnumType::USER_TASK_STATUS_COMPLETED; // 标记任务为已完成状态
            $data['complete_time'] = date(self::$dateTimeFormat, $currTime); // 完成时间

            // 发放奖品
            if ($task['prize_get_way'] == EnumType::TASK_PRIZE_GET_WAY_AUTO) {
                $data['is_get'] = EnumType::USER_TASK_IS_GET_YES; // 已领取
                $data['get_time'] = date(self::$dateTimeFormat, $currTime); // 领取时间
                $this->setSendPrizeData($task, $currTime);
            }
        }
    }

    /**
     * 设置发放奖品数据
     * @param array $params
     * @param int $currTime
     * @param int $reason
     * @return void
     */
    public function setSendPrizeData(array $params, int $currTime, int $reason = 29): void
    {
        foreach ($params['prize_list'] as $prize) {
            $userPrizeActId = $params['act_id'];
            if (isset($prize['act_id']) && $prize['act_id'] > 0) {
                $userPrizeActId = $prize['act_id'];
            }
            // 用户数据
            $prizeTypeChar = self::getPrizeTypeChar($prize['prize_type']);
            if (isset($this->userPrizeData[$prizeTypeChar][$userPrizeActId])) {
                $this->userPrizeData[$prizeTypeChar][$userPrizeActId] += $prize['prize_value'];
            } else {
                $this->userPrizeData[$prizeTypeChar][$userPrizeActId] = $prize['prize_value'];
            }

            if (!empty($params['task_id'])) { // 完成任务
                $type = EnumType::PRIZE_SEND_TYPE_DO_TASK;
                $linkId = $params['task_id'];
                $content = "完成任务-{$params['task_name']}，ID-{$params['task_id']}|发放奖品-{$prize['prize_name']}[+{$prize['prize_value']}]";
            } elseif (!empty($params['pobj_id'])) { // 抽奖
                $type = EnumType::PRIZE_SEND_TYPE_DRAW;
                $linkId = $params['pobj_id'];
                $content = "抽中奖项-{$params['pobj_name']}，ID-{$params['pobj_id']}|发放奖品-{$prize['prize_name']}[+{$prize['prize_value']}]";
            } else {
                $type = $linkId = 0;
                $content = '';
            }

            // 奖品发放记录
            $this->prizeLogs[] = [
                'act_id' => $params['act_id'],
                'uid' => $this->currUser['uid'],
                'prize_id' => $prize['prize_id'],
                'prize_name' => $prize['prize_name'],
                'prize_type' => $prize['prize_type'],
                'prize_unit' => $prize['prize_unit'],
                'prize_value' => $prize['prize_value'],
                'type' => $type,
                'link_id' => $linkId,
                'content' => $content,
                'create_time' => date(self::$dateTimeFormat, $currTime),
            ];
            // 用户余额变更日志
            $logTmp = [
                'uid' => $this->currUser['uid'],
                'num' => 0,
                'total' => 0,
                'reason' => $reason,
                'type' => 1,
                'content' => $content,
                'channel' => $this->currUser['channel'],
                'package_id' => $this->currUser['package_id'],
                'createtime' => $currTime,
            ];
            if ($prize['prize_type'] == EnumType::PRIZE_TYPE_CASH) { // cash记录
                $this->currUser['coin'] += $prize['prize_value'];
                $this->currUser['total_give_score'] += $prize['prize_value']; // 总赠送cash
                $logTmp['num'] = $prize['prize_value'];
                $logTmp['total'] = $this->currUser['coin'];
                $this->userCoinLogs[] = $logTmp;
            } elseif ($prize['prize_type'] == EnumType::PRIZE_TYPE_BONUS) { // bonus记录
                $this->currUser['bonus'] += $prize['prize_value'];
                $this->currUser['get_bonus'] += $prize['prize_value']; // 总获得bonus
                $logTmp['num'] = $prize['prize_value'];
                $logTmp['total'] = $this->currUser['bonus'];
                $this->userBonusLogs[] = $logTmp;
            }
        }
    }

    /**
     * 保存发放奖品数据
     * @return void
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public function saveSendPrizeData(array $waterMultiple = []): void
    {
        // 新增奖品发放记录
        if (!empty($this->prizeLogs)) {
            self::getPartTb('act_user_prize_log')->insert($this->prizeLogs);
        }
        // 新增cash记录
        if (!empty($this->userCoinLogs)) {
            self::getPartTb('coin')->insert($this->userCoinLogs);
        }
        // 新增bonus记录
        if (!empty($this->userBonusLogs)) {
            self::getPartTb('bonus')->insert($this->userBonusLogs);
        }

        // 更新用户余额
        $saveUserData = [];
        // 获取流水倍数配置
        $conf = SysConfService::getWaterMultipleConf();
        if (!empty($this->userPrizeData[EnumType::PRIZE_TYPE_CASH_CHAR])) {
            $saveUserData['coin'] = $this->currUser['coin'];
            $saveUserData['total_give_score'] = $this->currUser['total_give_score']; // 总赠送cash
            $saveUserData['need_cash_score_water'] = Db::raw(
                'need_cash_score_water + ' .
                bcmul(
                    (string)array_sum(array_values($this->userPrizeData[EnumType::PRIZE_TYPE_CASH_CHAR])),
                    (string)($waterMultiple['cash_water_multiple'] ?? $conf['cash_task_water_multiple'])
                )
            ); // 需要乘以cash流水倍数
        }
        if (!empty($this->userPrizeData[EnumType::PRIZE_TYPE_BONUS_CHAR])) {
            $saveUserData['bonus'] = $this->currUser['bonus'];
            $saveUserData['get_bonus'] =$this->currUser['get_bonus']; // 总获得bonus
            $saveUserData['need_bonus_score_water'] = Db::raw(
                'need_bonus_score_water + ' .
                bcmul(
                    (string)array_sum(array_values($this->userPrizeData[EnumType::PRIZE_TYPE_BONUS_CHAR])),
                    (string)($waterMultiple['bonus_water_multiple'] ?? $conf['bonus_task_water_multiple'])
                )
            ); // 需要乘以bonus流水倍数
        }
        if ($saveUserData) {
            self::getPoolTb('userinfo')->where('uid', $this->currUser['uid'])->update($saveUserData);
            // 更新用户日cash赠送数据
            if (!empty($this->userPrizeData[EnumType::PRIZE_TYPE_CASH_CHAR])) {
                $totalGiveCash = array_sum(array_values($this->userPrizeData[EnumType::PRIZE_TYPE_CASH_CHAR]));
                // 获取用户日数据
                $userDayData = self::getPartTb('user_day')->where('uid', $this->currUser['uid'])->first('uid');
                if ($userDayData) {
                    self::getPartTb('user_day')->where('uid', $this->currUser['uid'])
                        ->increment('total_give_score', $totalGiveCash);
                } else {
                    self::getPartTb('user_day')->insert([
                        'uid' => $this->currUser['uid'],
                        'puid' => $this->currUser['puid'],
                        'vip' => $this->currUser['vip'],
                        'channel' => $this->currUser['channel'],
                        'package_id' => $this->currUser['package_id'],
                        'total_give_score' => $totalGiveCash,
                    ]);
                }
            }
        }

        // 更新用户抽奖数据
        if (!empty($this->userPrizeData)) {
            $saveUserData = [];
            foreach ($this->userPrizeData as $prizeTypeChar => $uData) {
                $column = match ($prizeTypeChar) {
                    EnumType::PRIZE_TYPE_CASH_CHAR => 'win_cash',
                    EnumType::PRIZE_TYPE_BONUS_CHAR => 'win_bonus',
                    default  => 'draw_num',
                };
                foreach ($uData as $actId => $val) {
                    $saveUserData[$actId][$column] = $val;
                }
            }
            // 保存用户活动数据
            self::addActUserData($this->currUser['uid'], $saveUserData);
        }
    }

    /**
     * 添加用户活动数据
     * @param $uid
     * @param array $data
     * @param string $column
     * @param bool $coverVal
     * @return void
     */
    public static function addActUserData($uid, array $data, string $column = 'draw_num', bool $coverVal = false): void
    {
        // 获取用户活动数据
        $userActData = self::getPoolTb('act_user_data')
            ->where('uid', $uid)->pluck($column, 'act_id');
        foreach ($data as $act_id => $val) {
            if (isset($userActData[$act_id])) {
                $saveData = [];
                if ($coverVal) { // 覆盖数据
                    if (is_array($val)) {
                        $saveData = $val;
                    } else {
                        $saveData = [$column => $val];
                    }
                } else { // 累加数据
                    if (is_array($val)) {
                        foreach ($val as $k => $v) {
                            $saveData[$k] = Db::raw($k. '+' . $v);
                        }
                    } else {
                        $saveData[$column] = Db::raw($column. '+' . $val);
                    }
                }
                // 保存数据
                self::getPoolTb('act_user_data')
                    ->where('uid', $uid)->where('act_id', $act_id)
                    ->update($saveData);
            } else {
                $insertData = [
                    'act_id' => $act_id,
                    'uid' => $uid,
                ];
                if (is_array($val)) {
                    $insertData = array_merge($insertData, $val);
                } else {
                    $insertData[$column] = $val;
                }
                // 新增数据
                self::getPoolTb('act_user_data')->insert($insertData);
            }
        }
    }

    /**
     * 获取任务条件字段
     * @param int $conditionType
     * @return string[]
     */
    public static function getTaskConditionField(int $conditionType = 1): array
    {
        return match ($conditionType) {
            EnumType::TASK_CONDITION_TYPE_TERRACES_BET,EnumType::TASK_CONDITION_TYPE_GAME_BET => [
                'progress_value' => 'bet_num',
                'check_value' => 'bet_amount_min',
            ],
            EnumType::TASK_CONDITION_TYPE_TERRACES_WIN_BET,EnumType::TASK_CONDITION_TYPE_GAME_WIN_BET => [
                'progress_value' => 'bet_win_num',
                'check_value' => 'bet_win_amount_min',
            ],
            EnumType::TASK_CONDITION_TYPE_RECHARGE => [
                'progress_value' => 'recharge_num',
                'check_value' => 'recharge_amount_min',
            ],
            EnumType::TASK_CONDITION_TYPE_COMMENT_LIKE,EnumType::TASK_CONDITION_TYPE_GAME_COLLECT => [
                'progress_value' => 'done_num',
                'check_value' => 'check_value',
            ],
            EnumType::TASK_CONDITION_TYPE_INVITE => [
                'progress_value' => 'invite_num',
                'check_value' => 'check_value',
            ],
        };
    }

    /**
     * 获取给定条件值存在的条件类型
     * @param array $cTypes
     * @param int $conditionValue
     * @param array $params
     * @return array
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     * @throws \RedisException
     */
    public static function getTCTypesByGiveTypes(array $cTypes, int $conditionValue, array $params = []): array
    {
        // 获取任务列表
        $taskList = self::getTaskList(['c_types' => $cTypes], true);
        $hasTypes = [];
        foreach ($taskList as $task) {
            $checkField = self::getTaskConditionField($task['condition_type']);
            // 条件是否包含当前游戏ID
            if (!empty($params['game_id']) && !empty($task['task_conditions']['games']) && in_array($params['game_id'], $task['task_conditions']['games'])) {
                // 当前条件值是否大于任务条件值
                if ($conditionValue >= $task['task_conditions'][$checkField['check_value']]) {
                    $hasTypes[$task['condition_type']] = 1;continue;
                }
            }
            // 条件是否包含当前游戏厂商
            if (!empty($params['terrace_id']) && !empty($task['task_conditions']['terraces']) && in_array($params['terrace_id'], $task['task_conditions']['terraces'])) {
                // 当前条件值是否大于任务条件值
                if ($conditionValue >= $task['task_conditions'][$checkField['check_value']]) {
                    $hasTypes[$task['condition_type']] = 1;
                }
            }
        }
        return $hasTypes;
    }
}